home *** CD-ROM | disk | FTP | other *** search
/ Die Speccy' 97 / Die Speccy' 97.iso / amiga_system / the_aminet / dev / lang / python_src.lha / amigapython / objects / fileobject.c < prev    next >
C/C++ Source or Header  |  1995-10-22  |  15KB  |  847 lines

  1. /***********************************************************
  2. Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
  3. The Netherlands.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Stichting Mathematisch
  12. Centrum or CWI not be used in advertising or publicity pertaining to
  13. distribution of the software without specific, written prior permission.
  14.  
  15. STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
  16. THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
  18. FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  20. ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  21. OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  
  23. ******************************************************************/
  24.  
  25. /* File object implementation */
  26.  
  27. #include "allobjects.h"
  28. #include "modsupport.h"
  29. #include "structmember.h"
  30. #include "ceval.h"
  31.  
  32. #ifdef THINK_C
  33. #define HAVE_FOPENRF
  34. #endif
  35. #ifdef __MWERKS__
  36. /* Mwerks fopen() doesn't always set errno */
  37. #define NO_FOPEN_ERRNO
  38. #endif
  39.  
  40. #define BUF(v) GETSTRINGVALUE((stringobject *)v)
  41.  
  42. #include <errno.h>
  43.  
  44. typedef struct {
  45.     OB_HEAD
  46.     FILE *f_fp;
  47.     object *f_name;
  48.     object *f_mode;
  49.     int (*f_close) PROTO((FILE *));
  50.     int f_softspace; /* Flag used by 'print' command */
  51. } fileobject;
  52.  
  53. FILE *
  54. getfilefile(f)
  55.     object *f;
  56. {
  57.     if (f == NULL || !is_fileobject(f))
  58.         return NULL;
  59.     else
  60.         return ((fileobject *)f)->f_fp;
  61. }
  62.  
  63. object *
  64. getfilename(f)
  65.     object *f;
  66. {
  67.     if (f == NULL || !is_fileobject(f))
  68.         return NULL;
  69.     else
  70.         return ((fileobject *)f)->f_name;
  71. }
  72.  
  73. object *
  74. newopenfileobject(fp, name, mode, close)
  75.     FILE *fp;
  76.     char *name;
  77.     char *mode;
  78.     int (*close) FPROTO((FILE *));
  79. {
  80.     fileobject *f = NEWOBJ(fileobject, &Filetype);
  81.     if (f == NULL)
  82.         return NULL;
  83.     f->f_fp = NULL;
  84.     f->f_name = newstringobject(name);
  85.     f->f_mode = newstringobject(mode);
  86.     f->f_close = close;
  87.     f->f_softspace = 0;
  88.     if (f->f_name == NULL || f->f_mode == NULL) {
  89.         DECREF(f);
  90.         return NULL;
  91.     }
  92.     f->f_fp = fp;
  93.     return (object *) f;
  94. }
  95.  
  96. object *
  97. newfileobject(name, mode)
  98.     char *name, *mode;
  99. {
  100.     extern int fclose PROTO((FILE *));
  101.     fileobject *f;
  102.     f = (fileobject *) newopenfileobject((FILE *)NULL, name, mode, fclose);
  103.     if (f == NULL)
  104.         return NULL;
  105. #ifdef HAVE_FOPENRF
  106.     if (*mode == '*') {
  107.         FILE *fopenRF();
  108.         f->f_fp = fopenRF(name, mode+1);
  109.     }
  110.     else
  111. #endif
  112.     {
  113.         BGN_SAVE
  114.         f->f_fp = fopen(name, mode);
  115.         END_SAVE
  116.     }
  117.     if (f->f_fp == NULL) {
  118. #ifdef NO_FOPEN_ERRNO
  119.         if ( errno == 0 ) {
  120.             err_setstr(IOError, "Cannot open file");
  121.             DECREF(f);
  122.             return NULL;
  123.         }
  124. #endif
  125.         err_errno(IOError);
  126.         DECREF(f);
  127.         return NULL;
  128.     }
  129.     return (object *)f;
  130. }
  131.  
  132. void
  133. setfilebufsize(f, bufsize)
  134.     object *f;
  135.     int bufsize;
  136. {
  137.     if (bufsize >= 0) {
  138. #ifdef HAVE_SETVBUF
  139.         int type;
  140.         switch (bufsize) {
  141.         case 0:
  142.             type = _IONBF;
  143.             break;
  144.         case 1:
  145.             type = _IOLBF;
  146.             bufsize = BUFSIZ;
  147.             break;
  148.         default:
  149.             type = _IOFBF;
  150.         }
  151.         setvbuf(((fileobject *)f)->f_fp, (char *)NULL, type, bufsize);
  152. #endif /* HAVE_SETVBUF */
  153.     }
  154. }
  155.  
  156. static object *
  157. err_closed()
  158. {
  159.     err_setstr(ValueError, "I/O operation on closed file");
  160.     return NULL;
  161. }
  162.  
  163. /* Methods */
  164.  
  165. static void
  166. file_dealloc(f)
  167.     fileobject *f;
  168. {
  169.     if (f->f_fp != NULL && f->f_close != NULL) {
  170.         BGN_SAVE
  171.         (*f->f_close)(f->f_fp);
  172.         END_SAVE
  173.     }
  174.     if (f->f_name != NULL)
  175.         DECREF(f->f_name);
  176.     if (f->f_mode != NULL)
  177.         DECREF(f->f_mode);
  178.     free((char *)f);
  179. }
  180.  
  181. static object *
  182. file_repr(f)
  183.     fileobject *f;
  184. {
  185.     char buf[300];
  186.     sprintf(buf, "<%s file '%.256s', mode '%.10s' at %lx>",
  187.         f->f_fp == NULL ? "closed" : "open",
  188.         getstringvalue(f->f_name),
  189.         getstringvalue(f->f_mode),
  190.         (long)f);
  191.     return newstringobject(buf);
  192. }
  193.  
  194. static object *
  195. file_close(f, args)
  196.     fileobject *f;
  197.     object *args;
  198. {
  199.     int sts = 0;
  200.     if (!getnoarg(args))
  201.         return NULL;
  202.     if (f->f_fp != NULL) {
  203.         if (f->f_close != NULL) {
  204.             BGN_SAVE
  205.             errno = 0;
  206.             sts = (*f->f_close)(f->f_fp);
  207.             END_SAVE
  208.         }
  209.         f->f_fp = NULL;
  210.     }
  211.     if (sts == EOF)
  212.         return err_errno(IOError);
  213.     if (sts != 0)
  214.         return newintobject((long)sts);
  215.     INCREF(None);
  216.     return None;
  217. }
  218.  
  219. static object *
  220. file_seek(f, args)
  221.     fileobject *f;
  222.     object *args;
  223. {
  224.     long offset;
  225.     int whence;
  226.     int ret;
  227.     
  228.     if (f->f_fp == NULL)
  229.         return err_closed();
  230.     whence = 0;
  231.     if (!getargs(args, "l", &offset)) {
  232.         err_clear();
  233.         if (!getargs(args, "(li)", &offset, &whence))
  234.             return NULL;
  235.     }
  236.     BGN_SAVE
  237.     errno = 0;
  238.     ret = fseek(f->f_fp, offset, whence);
  239.     END_SAVE
  240.     if (ret != 0) {
  241.         err_errno(IOError);
  242.         clearerr(f->f_fp);
  243.         return NULL;
  244.     }
  245.     INCREF(None);
  246.     return None;
  247. }
  248.  
  249. #ifdef HAVE_FTRUNCATE
  250. static object *
  251. file_truncate(f, args)
  252.     fileobject *f;
  253.     object *args;
  254. {
  255.     long newsize;
  256.     int ret;
  257.     
  258.     if (f->f_fp == NULL)
  259.         return err_closed();
  260.     if (!getargs(args, "l", &newsize)) {
  261.         err_clear();
  262.         if (!getnoarg(args))
  263.                 return NULL;
  264.         BGN_SAVE
  265.         errno = 0;
  266.         newsize =  ftell(f->f_fp); /* default to current position*/
  267.         END_SAVE
  268.         if (newsize == -1L) {
  269.                 err_errno(IOError);
  270.             clearerr(f->f_fp);
  271.             return NULL;
  272.         }
  273.     }
  274.     BGN_SAVE
  275.     errno = 0;
  276.     ret = fflush(f->f_fp);
  277.     END_SAVE
  278.     if (ret == 0) {
  279.             BGN_SAVE
  280.         errno = 0;
  281.         ret = ftruncate(fileno(f->f_fp), newsize);
  282.         END_SAVE
  283.     }
  284.     if (ret != 0) {
  285.         err_errno(IOError);
  286.         clearerr(f->f_fp);
  287.         return NULL;
  288.     }
  289.     INCREF(None);
  290.     return None;
  291. }
  292. #endif /* HAVE_FTRUNCATE */
  293.  
  294. static object *
  295. file_tell(f, args)
  296.     fileobject *f;
  297.     object *args;
  298. {
  299.     long offset;
  300.     if (f->f_fp == NULL)
  301.         return err_closed();
  302.     if (!getnoarg(args))
  303.         return NULL;
  304.     BGN_SAVE
  305.     errno = 0;
  306.     offset = ftell(f->f_fp);
  307.     END_SAVE
  308.     if (offset == -1L) {
  309.         err_errno(IOError);
  310.         clearerr(f->f_fp);
  311.         return NULL;
  312.     }
  313.     return newintobject(offset);
  314. }
  315.  
  316. static object *
  317. file_fileno(f, args)
  318.     fileobject *f;
  319.     object *args;
  320. {
  321.     if (f->f_fp == NULL)
  322.         return err_closed();
  323.     if (!getnoarg(args))
  324.         return NULL;
  325.     return newintobject((long) fileno(f->f_fp));
  326. }
  327.  
  328. static object *
  329. file_flush(f, args)
  330.     fileobject *f;
  331.     object *args;
  332. {
  333.     int res;
  334.     
  335.     if (f->f_fp == NULL)
  336.         return err_closed();
  337.     if (!getnoarg(args))
  338.         return NULL;
  339.     BGN_SAVE
  340.     errno = 0;
  341.     res = fflush(f->f_fp);
  342.     END_SAVE
  343.     if (res != 0) {
  344.         err_errno(IOError);
  345.         clearerr(f->f_fp);
  346.         return NULL;
  347.     }
  348.     INCREF(None);
  349.     return None;
  350. }
  351.  
  352. static object *
  353. file_isatty(f, args)
  354.     fileobject *f;
  355.     object *args;
  356. {
  357.     long res;
  358.     if (f->f_fp == NULL)
  359.         return err_closed();
  360.     if (!getnoarg(args))
  361.         return NULL;
  362.     BGN_SAVE
  363.     res = isatty((int)fileno(f->f_fp));
  364.     END_SAVE
  365.     return newintobject(res);
  366. }
  367.  
  368. static object *
  369. file_read(f, args)
  370.     fileobject *f;
  371.     object *args;
  372. {
  373.     int n, n1, n2, n3;
  374.     object *v;
  375.     
  376.     if (f->f_fp == NULL)
  377.         return err_closed();
  378.     if (args == NULL)
  379.         n = -1;
  380.     else {
  381.         if (!getargs(args, "i", &n))
  382.             return NULL;
  383.     }
  384.     n2 = n >= 0 ? n : BUFSIZ;
  385.     v = newsizedstringobject((char *)NULL, n2);
  386.     if (v == NULL)
  387.         return NULL;
  388.     n1 = 0;
  389.     BGN_SAVE
  390.     for (;;) {
  391.         n3 = fread(BUF(v)+n1, 1, n2-n1, f->f_fp);
  392.         /* XXX Error check? */
  393.         if (n3 == 0)
  394.             break;
  395.         n1 += n3;
  396.         if (n1 == n)
  397.             break;
  398.         if (n < 0) {
  399.             n2 = n1 + BUFSIZ;
  400.             RET_SAVE
  401.             if (resizestring(&v, n2) < 0)
  402.                 return NULL;
  403.             RES_SAVE
  404.         }
  405.     }
  406.     END_SAVE
  407.     if (n1 != n2)
  408.         resizestring(&v, n1);
  409.     return v;
  410. }
  411.  
  412. /* Internal routine to get a line.
  413.    Size argument interpretation:
  414.    > 0: max length;
  415.    = 0: read arbitrary line;
  416.    < 0: strip trailing '\n', raise EOFError if EOF reached immediately
  417. */
  418.  
  419. static object *
  420. getline(f, n)
  421.     fileobject *f;
  422.     int n;
  423. {
  424.     register FILE *fp;
  425.     register int c;
  426.     register char *buf, *end;
  427.     int n1, n2;
  428.     object *v;
  429.  
  430.     fp = f->f_fp;
  431.     n2 = n > 0 ? n : 100;
  432.     v = newsizedstringobject((char *)NULL, n2);
  433.     if (v == NULL)
  434.         return NULL;
  435.     buf = BUF(v);
  436.     end = buf + n2;
  437.  
  438.     BGN_SAVE
  439.     for (;;) {
  440.         if ((c = getc(fp)) == EOF) {
  441.             clearerr(fp);
  442.             if (sigcheck()) {
  443.                 RET_SAVE
  444.                 DECREF(v);
  445.                 return NULL;
  446.             }
  447.             if (n < 0 && buf == BUF(v)) {
  448.                 RET_SAVE
  449.                 DECREF(v);
  450.                 err_setstr(EOFError,
  451.                        "EOF when reading a line");
  452.                 return NULL;
  453.             }
  454.             break;
  455.         }
  456.         if ((*buf++ = c) == '\n') {
  457.             if (n < 0)
  458.                 buf--;
  459.             break;
  460.         }
  461.         if (buf == end) {
  462.             if (n > 0)
  463.                 break;
  464.             n1 = n2;
  465.             n2 += 1000;
  466.             RET_SAVE
  467.             if (resizestring(&v, n2) < 0)
  468.                 return NULL;
  469.             RES_SAVE
  470.             buf = BUF(v) + n1;
  471.             end = BUF(v) + n2;
  472.         }
  473.     }
  474.     END_SAVE
  475.  
  476.     n1 = buf - BUF(v);
  477.     if (n1 != n2)
  478.         resizestring(&v, n1);
  479.     return v;
  480. }
  481.  
  482. /* External C interface */
  483.  
  484. object *
  485. filegetline(f, n)
  486.     object *f;
  487.     int n;
  488. {
  489.     if (f == NULL) {
  490.         err_badcall();
  491.         return NULL;
  492.     }
  493.     if (!is_fileobject(f)) {
  494.         object *reader;
  495.         object *args;
  496.         object *result;
  497.         reader = getattr(f, "readline");
  498.         if (reader == NULL)
  499.             return NULL;
  500.         if (n <= 0)
  501.             args = mkvalue("()");
  502.         else
  503.             args = mkvalue("(i)", n);
  504.         if (args == NULL) {
  505.             DECREF(reader);
  506.             return NULL;
  507.         }
  508.         result = call_object(reader, args);
  509.         DECREF(reader);
  510.         DECREF(args);
  511.         if (result != NULL && !is_stringobject(result)) {
  512.             DECREF(result);
  513.             result = NULL;
  514.             err_setstr(TypeError,
  515.                    "object.readline() returned non-string");
  516.         }
  517.         if (n < 0 && result != NULL) {
  518.             char *s = getstringvalue(result);
  519.             int len = getstringsize(result);
  520.             if (len == 0) {
  521.                 DECREF(result);
  522.                 result = NULL;
  523.                 err_setstr(EOFError,
  524.                        "EOF when reading a line");
  525.             }
  526.             else if (s[len-1] == '\n') {
  527.                 if (result->ob_refcnt == 1)
  528.                     resizestring(&result, len-1);
  529.                 else {
  530.                     object *v;
  531.                     v = newsizedstringobject(s, len-1);
  532.                     DECREF(result);
  533.                     result = v;
  534.                 }
  535.             }
  536.         }
  537.         return result;
  538.     }
  539.     if (((fileobject*)f)->f_fp == NULL)
  540.         return err_closed();
  541.     return getline((fileobject *)f, n);
  542. }
  543.  
  544. /* Python method */
  545.  
  546. static object *
  547. file_readline(f, args)
  548.     fileobject *f;
  549.     object *args;
  550. {
  551.     int n;
  552.  
  553.     if (f->f_fp == NULL)
  554.         return err_closed();
  555.     if (args == NULL)
  556.         n = 0; /* Unlimited */
  557.     else {
  558.         if (!getintarg(args, &n))
  559.             return NULL;
  560.         if (n == 0)
  561.             return newstringobject("");
  562.         if (n < 0)
  563.             n = 0;
  564.     }
  565.  
  566.     return getline(f, n);
  567. }
  568.  
  569. static object *
  570. file_readlines(f, args)
  571.     fileobject *f;
  572.     object *args;
  573. {
  574.     object *list;
  575.     object *line;
  576.  
  577.     if (f->f_fp == NULL)
  578.         return err_closed();
  579.     if (!getnoarg(args))
  580.         return NULL;
  581.     if ((list = newlistobject(0)) == NULL)
  582.         return NULL;
  583.     for (;;) {
  584.         line = getline(f, 0);
  585.         if (line != NULL && getstringsize(line) == 0) {
  586.             DECREF(line);
  587.             break;
  588.         }
  589.         if (line == NULL || addlistitem(list, line) != 0) {
  590.             DECREF(list);
  591.             XDECREF(line);
  592.             return NULL;
  593.         }
  594.         DECREF(line);
  595.     }
  596.     return list;
  597. }
  598.  
  599. static object *
  600. file_write(f, args)
  601.     fileobject *f;
  602.     object *args;
  603. {
  604.     char *s;
  605.     int n, n2;
  606.     if (f->f_fp == NULL)
  607.         return err_closed();
  608.     if (!getargs(args, "s#", &s, &n))
  609.         return NULL;
  610.     f->f_softspace = 0;
  611.     BGN_SAVE
  612.     errno = 0;
  613.     n2 = fwrite(s, 1, n, f->f_fp);
  614.     END_SAVE
  615.     if (n2 != n) {
  616.         err_errno(IOError);
  617.         clearerr(f->f_fp);
  618.         return NULL;
  619.     }
  620.     INCREF(None);
  621.     return None;
  622. }
  623.  
  624. static object *
  625. file_writelines(f, args)
  626.     fileobject *f;
  627.     object *args;
  628. {
  629.     int i, n;
  630.     if (f->f_fp == NULL)
  631.         return err_closed();
  632.     if (args == NULL || !is_listobject(args)) {
  633.         err_setstr(TypeError,
  634.                "writelines() requires list of strings");
  635.         return NULL;
  636.     }
  637.     n = getlistsize(args);
  638.     f->f_softspace = 0;
  639.     BGN_SAVE
  640.     errno = 0;
  641.     for (i = 0; i < n; i++) {
  642.         object *line = getlistitem(args, i);
  643.         int len;
  644.         int nwritten;
  645.         if (!is_stringobject(line)) {
  646.             RET_SAVE
  647.             err_setstr(TypeError,
  648.                    "writelines() requires list of strings");
  649.             return NULL;
  650.         }
  651.         len = getstringsize(line);
  652.         nwritten = fwrite(getstringvalue(line), 1, len, f->f_fp);
  653.         if (nwritten != len) {
  654.             RET_SAVE
  655.             err_errno(IOError);
  656.             clearerr(f->f_fp);
  657.             return NULL;
  658.         }
  659.     }
  660.     END_SAVE
  661.     INCREF(None);
  662.     return None;
  663. }
  664.  
  665. static struct methodlist file_methods[] = {
  666.     {"close",    (method)file_close, 0},
  667.     {"flush",    (method)file_flush, 0},
  668.     {"fileno",    (method)file_fileno, 0},
  669.     {"isatty",    (method)file_isatty, 0},
  670.     {"read",    (method)file_read, 0},
  671.     {"readline",    (method)file_readline, 0},
  672.     {"readlines",    (method)file_readlines, 0},
  673.     {"seek",    (method)file_seek, 0},
  674. #ifdef HAVE_FTRUNCATE
  675.     {"truncate",    (method)file_truncate, 0},
  676. #endif
  677.     {"tell",    (method)file_tell, 0},
  678.     {"write",    (method)file_write, 0},
  679.     {"writelines",    (method)file_writelines, 0},
  680.     {NULL,        NULL}        /* sentinel */
  681. };
  682.  
  683. #define OFF(x) offsetof(fileobject, x)
  684.  
  685. static struct memberlist file_memberlist[] = {
  686.     {"softspace",    T_INT,        OFF(f_softspace)},
  687.     {"mode",    T_OBJECT,    OFF(f_mode),    RO},
  688.     {"name",    T_OBJECT,    OFF(f_name),    RO},
  689.     /* getattr(f, "closed") is implemented without this table */
  690.     {"closed",    T_INT,        0,        RO},
  691.     {NULL}    /* Sentinel */
  692. };
  693.  
  694. static object *
  695. file_getattr(f, name)
  696.     fileobject *f;
  697.     char *name;
  698. {
  699.     object *res;
  700.  
  701.     res = findmethod(file_methods, (object *)f, name);
  702.     if (res != NULL)
  703.         return res;
  704.     err_clear();
  705.     if (strcmp(name, "closed") == 0)
  706.         return newintobject((long)(f->f_fp == 0));
  707.     return getmember((char *)f, file_memberlist, name);
  708. }
  709.  
  710. static int
  711. file_setattr(f, name, v)
  712.     fileobject *f;
  713.     char *name;
  714.     object *v;
  715. {
  716.     if (v == NULL) {
  717.         err_setstr(AttributeError, "can't delete file attributes");
  718.         return -1;
  719.     }
  720.     return setmember((char *)f, file_memberlist, name, v);
  721. }
  722.  
  723. typeobject Filetype = {
  724.     OB_HEAD_INIT(&Typetype)
  725.     0,
  726.     "file",
  727.     sizeof(fileobject),
  728.     0,
  729.     (destructor)file_dealloc, /*tp_dealloc*/
  730.     0,        /*tp_print*/
  731.     (getattrfunc)file_getattr, /*tp_getattr*/
  732.     (setattrfunc)file_setattr, /*tp_setattr*/
  733.     0,        /*tp_compare*/
  734.     (reprfunc)file_repr, /*tp_repr*/
  735. };
  736.  
  737. /* Interface for the 'soft space' between print items. */
  738.  
  739. int
  740. softspace(f, newflag)
  741.     object *f;
  742.     int newflag;
  743. {
  744.     int oldflag = 0;
  745.     if (f == NULL) {
  746.         /* Do nothing */
  747.     }
  748.     else if (is_fileobject(f)) {
  749.         oldflag = ((fileobject *)f)->f_softspace;
  750.         ((fileobject *)f)->f_softspace = newflag;
  751.     }
  752.     else {
  753.         object *v;
  754.         v = getattr(f, "softspace");
  755.         if (v == NULL)
  756.             err_clear();
  757.         else {
  758.             if (is_intobject(v))
  759.                 oldflag = getintvalue(v);
  760.             DECREF(v);
  761.         }
  762.         v = newintobject((long)newflag);
  763.         if (v == NULL)
  764.             err_clear();
  765.         else {
  766.             if (setattr(f, "softspace", v) != 0)
  767.                 err_clear();
  768.             DECREF(v);
  769.         }
  770.     }
  771.     return oldflag;
  772. }
  773.  
  774. /* Interfaces to write objects/strings to file-like objects */
  775.  
  776. int
  777. writeobject(v, f, flags)
  778.     object *v;
  779.     object *f;
  780.     int flags;
  781. {
  782.     object *writer, *value, *args, *result;
  783.     if (f == NULL) {
  784.         err_setstr(TypeError, "writeobject with NULL file");
  785.         return -1;
  786.     }
  787.     else if (is_fileobject(f)) {
  788.         FILE *fp = getfilefile(f);
  789.         if (fp == NULL) {
  790.             err_closed();
  791.             return -1;
  792.         }
  793.         return printobject(v, fp, flags);
  794.     }
  795.     writer = getattr(f, "write");
  796.     if (writer == NULL)
  797.         return -1;
  798.     if (flags & PRINT_RAW)
  799.         value = strobject(v);
  800.     else
  801.         value = reprobject(v);
  802.     if (value == NULL) {
  803.         DECREF(writer);
  804.         return -1;
  805.     }
  806.     args = mkvalue("(O)", value);
  807.     if (value == NULL) {
  808.         DECREF(value);
  809.         DECREF(writer);
  810.         return -1;
  811.     }
  812.     result = call_object(writer, args);
  813.     DECREF(args);
  814.     DECREF(value);
  815.     DECREF(writer);
  816.     if (result == NULL)
  817.         return -1;
  818.     DECREF(result);
  819.     return 0;
  820. }
  821.  
  822. void
  823. writestring(s, f)
  824.     char *s;
  825.     object *f;
  826. {
  827.     if (f == NULL) {
  828.         /* Do nothing */
  829.     }
  830.     else if (is_fileobject(f)) {
  831.         FILE *fp = getfilefile(f);
  832.         if (fp != NULL)
  833.             fputs(s, fp);
  834.     }
  835.     else if (!err_occurred()) {
  836.         object *v = newstringobject(s);
  837.         if (v == NULL) {
  838.             err_clear();
  839.         }
  840.         else {
  841.             if (writeobject(v, f, PRINT_RAW) != 0)
  842.                 err_clear();
  843.             DECREF(v);
  844.         }
  845.     }
  846. }
  847.